/**
 * 
 */
package Dungeon;


import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.Iterator;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import squarePackage.PlainSquare;
import squarePackage.RockSquare;
import squarePackage.SquareImp;
import Enumerations.Directions;
import Enumerations.Temperature;
import Exceptions.IllegalDimensionException;
import Obstacle.Door;
import Obstacle.Wall;

/**
 * @author Pieter
 *
 */
public class ShaftsTest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	
	Shaft<SquareImp> shaft;
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		shaft = new Shaft<SquareImp>(15, 20, 30, 10, 20, -5);
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}
	
	@Test 
	public final void testConstructorLevelsLegal() throws Exception{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,10,20,-5);
		assertEquals(10, shaft.getFixedX());
		assertEquals(20, shaft.getFixedY());
		assertEquals(-5, shaft.getFixedZ());
		
	}

	@Test (expected =IllegalArgumentException.class)
	public final void testConstructorLevelsIlleLegal() throws Exception{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,-10,20,-5);
	}
	
	@Test (expected =IllegalArgumentException.class)
	public final void testConstructorLevelsIlleLegalZfixed() throws Exception{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,-10,-20,-5);
	}
	
	@Test (expected =IllegalDimensionException.class)
	public final void testConstructorLevelsIlleLegalDimensions() throws Exception{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,10,25,-5);
	}
	
	@Test
	public final void isValidCoordinatesTest() throws IllegalDimensionException{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,10,20,-5);
		assertTrue(shaft.isValidCoordinate(10, 20, 8));
		assertTrue(shaft.isValidCoordinate(10, 20, 30));
		assertFalse(shaft.isValidCoordinate(11, 20, 30));
		assertFalse(shaft.isValidCoordinate(11, 20, 35));
		assertFalse(shaft.isValidCoordinate(15, 18, 30));
		assertFalse(shaft.isValidCoordinate(15, 18, -10));
		Shaft<SquareImp> otherShaft = new Shaft<SquareImp>(20, 20, 20, 10, -5, 10);
		assertTrue(otherShaft.isValidCoordinate(10, 8, 10));
		assertFalse(otherShaft.isValidCoordinate(10, 8, 11));
	}
	
	@Test
	public final void canHaveAsSquareTest() throws IllegalDimensionException{
		Shaft<SquareImp> shaft = new Shaft<SquareImp>(15,20,30,10,20,-5);
		assertFalse(shaft.canHaveAsSquare(new RockSquare()));
	}
	
	@Test
	public final void canHaveAsSquareAtTest(){
		assertFalse(shaft.canHaveAsSquareAtCoordinate(10, 20, 15, new RockSquare()));
	}
	
	@Test	(expected = IllegalDimensionException.class)
	public final void nodoorswithwallsbetween() throws IllegalDimensionException{
		Shaft<PlainSquare> newShaft = new Shaft<PlainSquare>(100, 100, 100, 10, -5, 10);
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.South, new Wall(new Door()));
		neigboor.setBorder(Directions.North, null);
		
		square.setMaterial(false);
		neigboor.setMaterial(false);
		
		square.setBorder(Directions.South, new Wall(new Door()));
		assertTrue(newShaft.noWallsWithDoorsAllowedBetweenSquares(square, 10, 1, 10));
		
		assertTrue(newShaft.canHaveAsSquareAtCoordinate(10, 1, 10, square));
		
		newShaft.addSquareToDungeon(10, 0, 10, square);
		newShaft.addSquareToDungeon(10, 1, 10, neigboor);
	}
	
	@Test	(expected = IllegalDimensionException.class)
	public final void secondTestWallsInbetween() throws IllegalDimensionException{
		Shaft<PlainSquare> newShaft = new Shaft<PlainSquare>(100, 100, 100, 10, -5, 10);
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.South, null);
		neigboor.setBorder(Directions.North, new Wall(new Door()));
		
		square.setMaterial(false);
		neigboor.setMaterial(false);
		
		square.setBorder(Directions.South, new Wall(new Door()));
		assertTrue(newShaft.noWallsWithDoorsAllowedBetweenSquares(square, 10, 1, 10));
		
		assertTrue(newShaft.canHaveAsSquareAtCoordinate(10, 1, 10, square));
		
		newShaft.addSquareToDungeon(10, 0, 10, square);
		newShaft.addSquareToDungeon(10, 1, 10, neigboor);
	}
	
	@Test	(expected = IllegalDimensionException.class)
	public final void ThirdTestWallsInbetween() throws IllegalDimensionException{
		Shaft<PlainSquare> newShaft = new Shaft<PlainSquare>(100, 100, 100, 10, -5, 10);
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.South, new Wall());
		neigboor.setBorder(Directions.North, new Wall(new Door()));
		
		square.setMaterial(false);
		neigboor.setMaterial(false);
		
		square.setBorder(Directions.South, new Wall(new Door()));
		assertTrue(newShaft.noWallsWithDoorsAllowedBetweenSquares(square, 10, 1, 10));
		
		assertTrue(newShaft.canHaveAsSquareAtCoordinate(10, 1, 10, square));
		
		newShaft.addSquareToDungeon(10, 0, 10, square);
		newShaft.addSquareToDungeon(10, 1, 10, neigboor);
		
		assertEquals(square.getBorderByDirection(Directions.South), neigboor.getBorderByDirection(Directions.North));
	}
	
	@Test
	public final void levelIterator() throws IllegalDimensionException{
	
		Shaft<PlainSquare> shaft = new Shaft<PlainSquare>(100,100,100,0,1,-5);
		PlainSquare s110 = new PlainSquare();
		PlainSquare s120 = new PlainSquare();
		s120.setBorder(Directions.South, new Wall());
		PlainSquare s130= new PlainSquare();
		s130.setBorder(Directions.South, new Wall());
		s130.setBorder(Directions.East, new Wall());
		PlainSquare s150= new PlainSquare();
		s150.setBorder(Directions.North, new Wall());
		s150.setBorder(Directions.East, new Wall());

		PlainSquare s220= new PlainSquare();
		s220.setBorder(Directions.North, new Wall());
		s220.setBorder(Directions.East, new Wall(new Door()));
		s220.getBorderByDirection(Directions.East).getDoor().openDoor();
		assertTrue(s220.getBorderByDirection(Directions.East).hasDoor());
		PlainSquare s230= new PlainSquare();
		PlainSquare s240= new PlainSquare();
		PlainSquare s250= new PlainSquare();
		s250.setBorder(Directions.East, new Wall());
		PlainSquare s330= new PlainSquare();
		PlainSquare s340= new PlainSquare();
		s340.setBorder(Directions.East, new Wall());
		s340.setBorder(Directions.South, new Wall());
		PlainSquare s430= new PlainSquare();
		s430.setBorder(Directions.North, new Wall());
		s430.setBorder(Directions.East, new Wall());
		s430.setBorder(Directions.South, new Wall(new Door()));
		s430.getBorderByDirection(Directions.South).getDoor().openDoor();
		PlainSquare s440= new PlainSquare();
		s440.setBorder(Directions.East, new Wall());
		PlainSquare s450= new PlainSquare();
		s450.setBorder(Directions.East, new Wall());
		PlainSquare s350= new PlainSquare();
		PlainSquare s610= new PlainSquare();
		PlainSquare s880 = new PlainSquare();
		s610.setBorder(Directions.West, new Wall());
		s610.setBorder(Directions.East, new Wall());
		s610.setBorder(Directions.South, new Wall(new Door()));
		s610.getBorderByDirection(Directions.South).getDoor().openDoor();
		PlainSquare s620= new PlainSquare();
		s620.setBorder(Directions.West, new Wall());
		s110.setTemperature(10, Temperature.CELCIUS);
		s110.setHumidity(new BigDecimal("0.3"));
		s120.setHumidity(new BigDecimal("0.2"));
		s120.setTemperature(10, Temperature.CELCIUS);
		s130.setTemperature(10, Temperature.CELCIUS);
		s130.setMaterial(false);
		s150.setMaterial(false);
		s220.setMaterial(false);
		s230.setMaterial(false);
		s240.setMaterial(false);
		s250.setMaterial(false);
		s330.setMaterial(false);
		s340.setMaterial(false);
		s430.setMaterial(false);
		s440.setMaterial(false);
		s450.setMaterial(false);
		s350.setMaterial(false);
		s610.setTemperature(10, Temperature.CELCIUS);
		s620.setTemperature(20, Temperature.CELCIUS);
		s880.setTemperature(30, Temperature.CELCIUS);
		s880.setMaterial(false);
		s110.setMaterial(false);
		s120.setMaterial(false);
		try {
			shaft.addSquareToDungeon(0, 1, 8, s110);
			shaft.addSquareToDungeon(0, 1, 9, s120);
			shaft.addSquareToDungeon(0, 1, 1, s130);
			shaft.addSquareToDungeon(0, 1, 7, s150);
			shaft.addSquareToDungeon(0, 1, 3, s220);
			shaft.addSquareToDungeon(0, 1, 10, s230);
			shaft.addSquareToDungeon(0, 1, 5, s240);
			shaft.addSquareToDungeon(0, 1, 19, s250);
			shaft.addSquareToDungeon(0, 1, 1, s330);
			shaft.addSquareToDungeon(0, 1, 13, s340);
			shaft.addSquareToDungeon(0, 1, 15, s430);
			shaft.addSquareToDungeon(0, 1, 6, s440);
			shaft.addSquareToDungeon(0, 1, 2, s450);
			shaft.addSquareToDungeon(0, 1, 4, s350);
			shaft.addSquareToDungeon(0, 1, 12, s610);
			shaft.addSquareToDungeon(0, 1, 11, s620);
			shaft.addSquareToDungeon(0, 1, 0, s880);
		} catch (Exception e) {
			
		}
		System.out.println("ZONDER ITERATOR");
		for(Object square : shaft.getAllSquaresInDungeon()){
		System.out.println(square);
		}
		
		System.out.println("MET ITERATOR");
		Iterator<PlainSquare> it = shaft.iterator();
		while(it.hasNext()){
		System.out.println(it.next());
		}
	}

}
